# koroFileHeader at Yungoal acer
# Create: 2021-07-05 12:30:23
# LastEdit: 2021-07-06 15:02:59
"""CN服务器配置NTP和时区
内网NTP服务器地址: 10.157.52.73,10.157.52.74
时区配置为上海: timedatectl set-timezone "Asia/Shanghai"
"""
__author__ = '749B'

import os, sys
BASE_DIR = os.getcwd()
sys.path.append(BASE_DIR)

# pylint: disable = import-error
from azure_client.models import RuncmdCheck, RuncmdTask
from utils.blueking import job_start, job_success, job_fail

from typing import Optional, List, Tuple
_Check = Tuple[bool, str]


class TimedateCheck(RuncmdCheck):

    @staticmethod
    def init_argparse_hook(parser):
        dns_option = parser.add_argument_group('NTP Option', 'NTP检查使用的选项')
        dns_option.add_argument('--ntp', required=True, help="逗号隔开的NTP服务器地址")
        return

    def parse_linux(self, task: RuncmdTask) -> _Check:
        """
        sync:yes
        server:10.157.52.73|10.157.52.74
        timezone:+0800
        """
        errors = []
        check_list = {'sync': False, 'server': False, 'timezone': False}
        lines = self.std_out.strip().splitlines()
        for line in lines:
            if ':' not in line:
                continue
            k, v = line.split(':', 1)
            if k not in check_list:
                continue
            check_list[k] = v
            
        for k, v in check_list.items():
            if not v:
                errors.append(f'{k}:未能获取值')
                continue
            if k == 'sync':
                if str(v).lower() != 'yes':
                    errors.append(f'{k}:{v}')
            if k == 'server':
                server_list = str(v).split('|')
                for i in self.args.ntp.split(','):
                    if i not in server_list:
                        errors.append(f"未设置NTP:{i}")
            if k == 'timezone':
                if str(v).lower() != '+0800':
                    errors.append(f'时区错误:{v}')

        if errors:
            return False, '|'.join(errors)
        return True, "OK"        

    def parse_windows(self, task: RuncmdTask) -> _Check:
        """
        查source只能查到一个源的地址
        status:Running
        source:10.157.52.73
        tzutil:China Standard Time

        # 服务未启动，拿不到source。好在只要用source匹配IP地址，注意结尾可能包含空白符
        status:Stopped
        source: 服务尚未启动。 (0x80070426)
        """
        errors = []
        check_list = {'status': False, 'source': False, 'tzutil': False}
        lines = self.std_out.strip().splitlines()
        for line in lines:
            if ':' not in line:
                continue
            k, v = line.split(':', 1)
            if k not in check_list:
                continue
            check_list[k] = v
            
        for k, v in check_list.items():
            if not v:
                errors.append(f'{k}:未能获取值')
                continue
            if k == 'status':
                if str(v).lower() != 'running':
                    errors.append(f'{k}:{v}')
            if k == 'source':
                if str(v).strip() not in self.args.ntp.split(','):
                    errors.append(f"NTP设置错误:{v}")
            if k == 'tzutil':
                if str(v).lower() != 'China Standard Time'.lower():
                    errors.append(f'时区错误:{v}')

        if errors:
            return False, '|'.join(errors)
        return True, "OK"   


def main(args: Optional[List[str]] = None) -> None:
    """主函数"""
    check_obj = TimedateCheck(args, SCRIPTS_LINUX, SCRIPTS_WINSOWS, CHECK_ITEMS)
    check_obj.run()
    
    if check_obj.fail_count:
        job_fail("不合规的记录数: %s" % check_obj.fail_count)
    job_success()


# pylint: disable = anomalous-backslash-in-string
SCRIPTS_LINUX = """\
systemctl --version &>/dev/null
if [ $? -eq 0 ]; then
    systemctl is-active ntpd &>/dev/null && service=ntpd
    systemctl is-active chronyd &>/dev/null && service=chronyd
else
    chkconfig --list ntpd &>/dev/null && service=ntpd
    chkconfig --list chronyd &>/dev/null && service=chronyd
fi

case "$service" in
ntpd)
    ntpstat | grep -Eq '^\s*synchronised\s' && echo sync:yes || echo sync:no
    grep -Eq '^server' /etc/ntp.conf && awk 'BEGIN{ORS=":";print "server";ORS="|"} /^server/ {print $2}' /etc/ntp.conf | sed 's/.$/\\n/' || echo server:ServerNotSet
    ;;
chronyd)
    timedatectl | awk '/^\s*NTP synchronized:/ {print "sync:"$3}'
    grep -Eq '^server' /etc/chrony.conf && awk 'BEGIN{ORS=":";print "server";ORS="|"} /^server/ {print $2}' /etc/chrony.conf | sed 's/.$/\\n/' || echo server:ServerNotSet
    ;;
*)
    echo sync:NoService
    echo server:NoService
    ;;
esac

date +"timezone:%z"
"""

SCRIPTS_WINSOWS = """\
$status = Get-Service W32Time -ErrorAction SilentlyContinue
if ($?) {
    $status | %{Write-Host -Separator "" "status:" $_.Status}
    $source = w32tm /query /source
    Write-Host -Separator "" "source:" ($source -split ",", 2)[0] 
} else {
    Write-Host status:W32TimeNotFound
    Write-Host source:W32TimeNotFound
}    
$tzutil = tzutil /g
Write-Host -Separator "" "tzutil:" $tzutil
"""

CHECK_ITEMS = ['sync', 'server', 'timezone']

if __name__ == '__main__':

    job_start()

    ###### 可在此处开始编写您的脚本逻辑代码
    ###### iJobs中执行脚本成功和失败的标准只取决于脚本最后一条执行语句的返回值
    ###### 如果返回值为0，则认为此脚本执行成功，如果非0，则认为脚本执行失败

    main()



